/*	Copyright 2007 - Xavier Baro (xbaro@cvc.uab.cat)

	This file is part of eapmlib.

    Eapmlib is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 3 of the License, or any 
	later version.

    Eapmlib is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
/*! \file NaiveBayesModel.h
\brief Naive Bayes Model class header
\author Xavier Bar Sol

This file contains the declaration of the Naive Bayes Model Class. This clase implements
this type of probabilistic model. 
*/

#ifndef __NAIVEBAYESMODEL_H__
#define __NAIVEBAYESMODEL_H__

#include "EvolutiveLib.h"
#include "ProbModel.h"
#include "AbsVarAbstractionSet.h"

using namespace NBE;

namespace Evolutive {

	//! Defines the types of population generation
	enum EVOLUTIVELIB_API POBGEN_METHOD {POPGEN_PROB,POPGEN_VAL};

	class EVOLUTIVELIB_API CNaiveBayesModel : public CProbModel
	{
		//! Methods
	public:
		//! Default constructor		
		CNaiveBayesModel(void);

		//! Default destructor
		virtual ~CNaiveBayesModel(void);

		//! Indicates when the model is at a standstill(from base class)
		virtual bool IsStatic(double Tolerance);

		//! Generates a new population using the probability distribution(from base class)
		virtual void NewPopulation(CPopulation &Population,CODING_METHOD ModelCode,CEvaluator *Evaluator);

		//! Updates the model using an individual (from base class)
		virtual void Update(CChromosome &C);

		//! Estimate a model from the data (from base class)
		virtual void Estimate(int NumIndividuals,CPopulation &Population);	

		//! Estimate a model from a data matrix
		void Estimate(int NumIndividuals,int Dimension,double *Data);	

		//! Initialize the probability model (from base class)
		virtual void InitializeModel(int NumVars,CPopulation &Population);

		//! Sets the generation method
		void SetGenerationMethod(POBGEN_METHOD GenMethod);

		//! Save the model
		void Save(string FileName);

		//! Load a model
		void Load(string FileName);

		//! Retrieve the number of clusters in the estimated model
		int GetNumClusters(void);

		//! Retrieve parameters from the estimated model
		void GetParameters(double *Priors,double *Centres,double *Variances);

		//! Classify the given vector to the cluster with maximum likelihood
		int Classify(double *Data,double *Prob=NULL);

		//! Set the maximum number of iterations for the NBE algorithm (-1 to stop only by deltas)
		void SetMaxIters(int NumIters);

		//! Set the minimum weight change
		void SetMinWeightChange(double MinWeight);

		//! Set the fraction of clusters to prune
		void SetPruneFrac(double Fraction);

		//! Set the number of iterations between pruning processes
		void SetPruneFreq(int NumIters);

		//! Set the initial number of clusters
		void SetInitialNumClusters(int NumClusters);

		//! Set EM delta. Used to stop the EM step
		void SetEMDelta(double Delta);

		//! Set Cluster addition delta. Used to stop the addition of new clusters
		void SetAddDelta(double Delta);

		//! Set the default initial variance factor. New Gaussian are created with the overall observed variable variance divided by this factor
		void SetVarDiv(double VarDiv);

		//! Activate of disable the elimination of cluster centers (to avoid overfitting)
		void SetRemoveClusterCentres(bool Flag);

		//! Set the fraction of samples to use as hold-out set
		void SetHoldOutFrac(double Fraction);
		
	private:
		//! Prepare learning data
		void PrepareData(int NumIndividuals,CPopulation *Population);
		void PrepareData(int NumIndividuals,int Dimension,double *Data);

		//! Extract the schema from the given population
		void ExtractSchema(void);

		//! Estimate the Naive Bayes Model
		void EstimateModel(void);

		//! Classify the give`n population to the cluster with maximum likelihood
		int Classify(CChromosome *C);
					
		//! Attributes
	private:		
		//! Method to generate new populations
		POBGEN_METHOD m_GenerationMethod;

		//! Variance of continuous variables
		double m_VarDiv;

		//! Holdout set percentage. 
		double m_HoldoutPercentage;

		//! Minimum likelihood improvement to continue with the EM loop
		double m_MinLlChangeEM;

		//! Minimum likelihood improvement to continue with the Addition loop
		double m_MinLlChangeAdd;

		//!  Minimum weight change to continue (stop criteria)
		double m_MinWeightChange;

		//! Incremental abstraction loading
		int m_AbsToLoad;

		//! Early stopping
		int m_FixedEMIters;

		//! Abstraction pruning
		double m_PruneFrac;
		int m_PruneFreq;

		//! Flag that indicates when the centers are removed from the training data
		bool m_RemoveClusterCenters;

		//! Save the best model
		bool m_SaveBestModel;

		//! Rerun option for the NBE algorithm
		bool m_Rerun;

		//! Number of samples abstractions
		bool m_SampledAbs;

		//! NBE Model representation
		AbsVarAbstractionSet *m_Model;

		//! Schema of the represented data
		VarSchema m_ModelSchema;

		//! Variables set
		VarSet m_VarSet;

		//! Observations
		GrowArray<VarSet> m_Observations;

		//! Training data
		GrowArray<VarSet> m_TrainSet;

		//! Validation data
		GrowArray<VarSet> m_HoldoutSet;
	};	
}

#endif // __NAIVEBAYESMODEL_H__
